package game

import game.business.*
import game.enums.Direction
import game.model.*
import game.model.impl.*
import javafx.scene.input.KeyCode
import javafx.scene.input.KeyEvent
import org.itheima.kotlin.game.core.Window
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import java.util.concurrent.CopyOnWriteArrayList

class GameWindows : Window(
        title = "坦克大战"
        , width = Config.gameWidth
        , height = Config.gameHeight
) {

    private var gameOver: Boolean = false

    //管理页面元素集合
//    private val views = arrayListOf<View>()
    //线程安全集合
    private val views = CopyOnWriteArrayList<View>()

    //lateinit延迟创建
    private lateinit var tank: Tank

    //敌方数量
    private var enemyTotalSize = 20

    //敌方坦克在界面上最多显示几个
    private var enemyActiveSize = 6

    //敌方出生点
    private val enemyBornLocation = arrayListOf<Pair<Int, Int>>()

    //出生地点下标
    private var bornIndex = 0

    override fun onCreate() {
//        val file = File(javaClass.getResource("../map/1.map").path)
        var resourceAsStream = javaClass.getResourceAsStream("/map/1.map")
        var reader = BufferedReader(InputStreamReader(resourceAsStream,"utf-8"))
        val lines = reader.readLines()
//        val lines = file.readLines();
        var lineNum = 0
        lines.forEach { line ->
            var columnNum = 0
            line.toCharArray().forEach { column ->
                when (column) {
                    '砖' -> views.add(Wall(columnNum * Config.block, lineNum * Config.block))
                    '铁' -> views.add(Steel(columnNum * Config.block, lineNum * Config.block))
                    '水' -> views.add(Water(columnNum * Config.block, lineNum * Config.block))
                    '草' -> views.add(Grass(columnNum * Config.block, lineNum * Config.block))
                    '敌' -> enemyBornLocation.add(Pair(columnNum * Config.block, lineNum * Config.block))
                }
                columnNum++;
            }
            lineNum++;
        }

        //添加我方坦克
        tank = Tank(Config.block * 10, Config.block * 10)
        views.add(tank)

        //添加大本营
        views.add(Camp(Config.gameWidth / 2 - Config.block, Config.gameHeight - Config.block * 3 / 2))
    }

    override fun onDisplay() {
        views.forEach { it.draw() }
    }

    override fun onKeyPressed(event: KeyEvent) {
        if (gameOver) return
        when (event.code) {
            KeyCode.W -> {
                tank.move(Direction.up)
            }
            KeyCode.S -> {
                tank.move(Direction.down)
            }
            KeyCode.A -> {
                tank.move(Direction.left)
            }
            KeyCode.D -> {
                tank.move(Direction.right)
            }
            KeyCode.ENTER -> {
                //发射子弹
                var bullet = tank.shot()
                //交给views管理
                views.add(bullet)
            }
        }
    }

    override fun onRefresh() {
        //业务逻辑

        //销毁物体
        views.filterIsInstance<DestroyAble>().forEach {
            //判断物体是否需要销毁
            if (it.isDestroyed()) {
                views.remove(it)

                if (it is Enemy)
                    enemyTotalSize--

                var showDestroy = it.showDestroy()
                showDestroy?.let {
                    views.addAll(showDestroy)
                }
            }
        }


        //判断游戏是否结束
        if (gameOver) return

        //判断运动的物体和阻塞的物体是否发生碰撞
        //找到运动的物体
        views.filterIsInstance<Movable>().forEach { move ->
            //找到阻塞的物体
            var badDirection: Direction? = null
            var badBlock: BlockAble? = null
            //不要和自己比较
            views.filterIsInstance<BlockAble>().forEach blockTag@{ block ->   //循环标记
                //遍历集合，找到是否发生碰撞   as kotlin强制转换
                //不和自己比较 (既是Movable 也是 BlockAble 的情况)
                if (block == move) return@blockTag
                //获取碰撞的方向
                val direction = move.willCollision(block)
                direction?.let {
                    //移动的发现碰撞。跳出循环
                    badDirection = direction
                    badBlock = block
                    return@blockTag
                }
            }
            //找到和move碰撞的block，找到会碰撞的方向
            //通知可以移动的物体，会在哪个方向和哪个物体发生碰撞
            move.notifyCollision(badDirection, badBlock)
        }

        //检测自动移动的物体，让他们自己动起来
        views.filterIsInstance<AutoMove>().forEach {
            it.autoMove()
        }

        //检测 具备攻击能力的和被攻击能力的物体是否发生碰撞
        // 1 具备攻击能力的
        views.filterIsInstance<AttackAble>().forEach { attack ->
            // 2 具备受攻击能力的
            views.filterIsInstance<SufferAble>().forEach sufferTag@{ suffer ->
                if (attack.source == suffer || attack == suffer) return@sufferTag
                //3 判断是否产生碰撞
                if (attack.isCollision(suffer)) {
                    //产生判断 找到碰撞者
                    //通知攻击者  产生碰撞
                    attack.notifyAttack(suffer)
                    //通知被攻击者 产生碰撞
                    var sufferView = suffer.notifySuffer(attack)
                    sufferView?.let {
                        views.addAll(sufferView)
                    }
                    return@sufferTag
                }
            }
        }


        //检测自动设计能力
        views.filterIsInstance<AutoShot>().forEach {
            val shot = it.autoShot()
            shot?.let {
                views.add(shot)
            }
        }

        //检测游戏是否结束
        if (views.filterIsInstance<Camp>().isEmpty() or (enemyTotalSize <= 0) or (views.filterIsInstance<Tank>().isEmpty()))
            gameOver = true

        //检测敌方出生
        //判断当前页面上敌方的数量，小于激活数量
        if (( enemyTotalSize > 0 ) and ( views.filterIsInstance<Enemy>().size < enemyActiveSize)) {
            val index = bornIndex % enemyBornLocation.size
            var pair = enemyBornLocation[index]
            views.add(Enemy(pair.first, pair.second))
            bornIndex++
        }

    }
}